<?php


namespace App\Services;

use App\Models\Partition as PartitionModel;
use App\Models\PartitionAdjustmentAmount;
use App\Models\PartitionTable;
use App\Models\PartitionTableRecord;
use D1M\Common\Exceptions\BusinessException;
use Illuminate\Support\Facades\DB;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class Partition extends Base
{


    public function list($storeId)
    {
        $partitions = $this->getAllPartitions($storeId);
        $ids = array_column($partitions,'id');
        $tables = $this->getPartitionTables($ids);
        //dump($partitions);die;
        foreach ($partitions as $k=>$v)
        {
            $v->deleted = $v->deleted_at==null?0:1;
            $v->count=0;
            $v->partition_tables=[];

            foreach ($tables as $t)
            {
                if($v->id==$t['partition_id'])
                {
                    if(!$t['deleted_at']) $v->count++;
                    $t['table_number'] = $v->name.$t['number'];
                    $t['deleted'] = $t['deleted_at']?1:0;
                    array_push($v->partition_tables,$t);
                }
            }
        }
        return $partitions;
    }


    public function createPartition($storeId,$name)
    {
        $this->checkPartitionName($storeId,$name);
//        \App\Models\Partition::
    }


    public function storeNew($data)
    {
        $storeId = $data['store_id'];
        $partitions = $data['partitions'];

        //获取所有的桌台数据
        $oldPartitions = $this->getAllPartitions($storeId);
        $ids = array_column($oldPartitions,'id');
        $oldTables = $this->getPartitionTables($ids);

        $oldPartitions = array_column($oldPartitions,null,'id');
        $oldTables = array_column($oldTables,null,'id');

        $usedTables = [];
        foreach ($oldPartitions as $p){
            $p->used = $p->tableCount =  0;
            $p->status = [];
            foreach ($oldTables as $t)
            {
                if($t['partition_id']==$p->id) {
                    $p->tableCount ++ ;
                    if(!$p->used) $p->used = $t['state'];
                    if($t['status']==2){
                        array_push($p->status,$p->name.$t['number']);
                        array_push($usedTables,$p->name.$t['number']);
                    }

                }
            }
        }

        //只要有使用中的桌台就不允许编辑
//        if($usedTables){
//            throw new BusinessException('桌号'.implode('、',$usedTables).'正在使用中，无法进行编辑或删除操作',-5);
//        }

        $partitionsInsert = $partitionsUpdate = $partitionsDelIds = $partitionsDel = [];
        $partitionTablesInsert = $partitionTablesUpdate = $partitionTablesDelIds =$partitionTablesDel = [];

        $updateCountPartitions = 0;
        $partitionNames = [];
        $partitionOrder = [];
        foreach ($partitions as $v){

            /********************************桌台********************************/
            $updateCountPartitionTables = 0;
            $partitionTableNumbers = [];
            $partitionTableOrder = [];
            //$v['state']=0;
            $v['state']=[];
            foreach ($v['partition_tables'] as $y){
                if($y['state']){
                    //$v['state']=$y['state'];
                    array_push($v['state'],$v['name'].$y['number']);
                }
                $partitionTableData = [
                    'partition'=>$v['name'],
                    'partition_id'=>$v['id'],
                    'number'=>$y['number'],
                    'order'=>$y['order'],
                    'max'=>$y['max'],
                    'state'=>$y['state'],
                    'status'=>$y['state']
                ];

                if($y['id']==0 && $v['deleted']==false){
                    array_push($partitionTablesInsert,$partitionTableData);
                    array_push($partitionTableNumbers,$y['number']);
                    if(in_array($y['order'],$partitionTableOrder))
                    {
                        throw new BusinessException('新增数据排序重复,桌号:'.$v['name'].$y['number']);
                    }
                    array_push($partitionTableOrder,$y['order']);
                }

                //编辑或删除 区域
                if($y['id']>0){
                    $updateData = [
                        'number'=>$y['number'],
                        'order'=>$y['order'],
                        'max'=>$y['max'],
                        'state'=>$y['state'],
                        //'status'=>$y['state'],
                        'status'=>$oldTables[$y['id']]['status']??$y['state'],
                    ];
                    $updateCountPartitionTables ++ ;
                    if(!isset($oldTables[$y['id']])){
                        throw new BusinessException('删除桌台数据异常，桌台号'.$v['name'].$y['number']);
                    }
                    if($oldTables[$y['id']]['deleted_at']){
                        $partitionTablesDel[$y['id']] = $updateData;
                        continue;
                    }

                    if($y['deleted'] && $oldTables[$y['id']]['deleted_at']===null){
                        //删除 todo 确认不在启用中
//                        if($oldTables[$y['id']]['status']==2)throw new BusinessException('区域内有桌台在使用中不可删除，区域名:'.$v['name'].'桌台号'.$y['number']);
                        if($oldTables[$y['id']]['status']==2)throw new BusinessException('桌号'.$v['name'].$y['number'].'正在使用中，无法进行删除操作',-5);
//                        if($y['state'])throw new BusinessException('区域内有桌台在启用中不可删除，区域名:'.$v['name'].'桌台号'.$y['number']);
                        if($y['state'])throw new BusinessException('桌号'.$v['name'].$y['number'].'正在启用中，无法进行删除操作',-5);
                        $updateData['deleted_at'] = date('Y-m-d H:i:s');
                        $partitionTablesDel[$y['id']] = $updateData;
                    }
                    if(!$y['deleted']){
                        //if($oldTables[$y['id']]['deleted_at']) throw new BusinessException('已删除桌台不可再编辑，桌台号'.$y['name']);
                        //update  todo 对比数据是否真的有更新
                        array_push($partitionTableNumbers,$y['number']);
                        if(($y['number']!=$oldTables[$y['id']]['number']  || $y['state']!=$oldTables[$y['id']]['state'] || $y['max']!=$oldTables[$y['id']]['max'])
                            && $oldTables[$y['id']]['status']==2){
                            throw new BusinessException('桌号'.$v['name'].$y['number'].'正在使用中，无法进行编辑或删除操作',-5);
                        }


                        if($y['number']!=$oldTables[$y['id']]['number'] || $y['order']!=$oldTables[$y['id']]['order'] ||
                            $y['state']!=$oldTables[$y['id']]['state'] || $y['max']!=$oldTables[$y['id']]['max']){
                            //要更新，确认下边没有使用中桌台
                            //if($oldTables[$y['id']]['status']==2)throw new BusinessException('桌号'.$v['name'].$y['number'].'正在使用中，无法进行编辑或删除操作',-5);
                            //array_push($partitionTablesUpdate,$partitionTableData);
                            $partitionTablesUpdate[$y['id']] = $updateData;

                        }
                        if(in_array($y['order'],$partitionTableOrder))
                        {
                            throw new BusinessException('编辑数据排序重复,桌号:'.$v['name'].$y['number']);
                        }
                        array_push($partitionTableOrder,$y['order']);
                    }
                }

            }


            /********************************区域*********************************/
            $partitionData = [
                'store_id'=>$storeId,
                'name'=>$v['name'],
                'order'=>$v['order'],
            ];
            //新增区域
            if($v['id']===0){
                //if($v['deleted'])throw new BusinessException('新增区域数据异常');
                array_push($partitionsInsert,$partitionData);
                array_push($partitionNames,$v['name']);
                if(in_array($v['order'],$partitionOrder))
                {
                    throw new BusinessException('新增数据排序重复,区域名:'.$v['name']);
                }
                array_push($partitionOrder,$v['order']);
            }

            //编辑或删除 区域
            if($v['id']>0){
                $updateCountPartitions ++;
                if(!isset($oldPartitions[$v['id']])){
                    throw new BusinessException('删除区域数据异常，区域名:'.$v['name']);
                }
                if($updateCountPartitionTables != $oldPartitions[$v['id']]->tableCount)
                {
                    throw new BusinessException('数据异常，区域内桌台数量不等于原始数量，区域name:'.$v['name']);
                }

                if($oldPartitions[$v['id']]->deleted_at){
                    $partitionsDel[$v['id']] = $partitionData;
                    continue;
                }
                if($v['deleted']){
                    //删除 todo 确认不在启用中
                    if($oldPartitions[$v['id']]->status)throw new BusinessException('桌号'.implode('、',$oldPartitions[$v['id']]->status).'正在使用中，无法进行删除操作',-5);
//                    if($oldPartitions[$v['id']]->status)throw new BusinessException('桌号'.implode('、',$usedTables).'正在使用中，无法进行删除操作',-5);
                    if($v['state'])throw new BusinessException('桌号'.implode('、',$v['state']).'正在启用中，无法进行删除操作',-5);
                    array_push($partitionsDelIds,$v['id']);
                    $partitionsDel[$v['id']] = [
                        'name'=>$v['name'],
                        'order'=>$v['order'],
                        //'order'=>0,
                        'deleted_at'=>date('Y-m-d H:i:s')
                    ];
                    continue;
                }
                if(!$v['deleted']){
                    array_push($partitionNames,$v['name']);
                    //if($oldPartitions[$v['id']]->deleted_at) throw new BusinessException('已删除区域不可再编辑，区域name'.$v['name']);
                    //update  对比数据是否真的有更新   区域不参与排序校验
                    if($oldPartitions[$v['id']]->status && $v['name']!=$oldPartitions[$v['id']]->name)throw new BusinessException('桌号'.implode('、',$oldPartitions[$v['id']]->status).'正在使用中，无法进行编辑操作',-5);

                    if($v['name']!=$oldPartitions[$v['id']]->name || $v['order']!=$oldPartitions[$v['id']]->order){
                        //要更新，确认下边没有使用中桌台
                        //if($oldPartitions[$v['id']]->status)throw new BusinessException('桌号'.implode('、',$oldPartitions[$v['id']]->status).'正在使用中，无法进行编辑操作',-5);
                        //array_push($partitionsUpdate,$partitionData);
                        $partitionsUpdate[$v['id']] = $partitionData;
                    }
                    if(in_array($v['order'],$partitionOrder))
                    {
                        throw new BusinessException('新增数据排序重复,区域名:'.$v['name']);
                    }
                    array_push($partitionOrder,$v['order']);
                }

            }




            //判断区域内桌号是否重复  todo 去除已删除的桌台   桌台编辑时可以改变区域吗？？？   重复和数量限制不包含已删除的数据
            //$tableNumbers = array_column($v['partition_tables'],'number');
            if(count($partitionTableNumbers)>300){
                throw new BusinessException('每个区域最多添加300张桌子');
            }
            if(count(array_unique($partitionTableNumbers)) != count($partitionTableNumbers)){
                throw new BusinessException('区域内桌号不可重复');
            }

        }
        //判断区域名称是否重复 todo 去除已删除的区域  区域数量限制包含已删除数据

        if(count($partitionNames)>10){
            throw new BusinessException('最多10个区域');
        }
        if(count(array_unique($partitionNames)) != count($partitionNames)){
            throw new BusinessException('区域名称不可重复');
        }

//        dump($partitionsInsert);
//        dump($partitionsUpdate);
//        dump($partitionsDelIds);
//        dump($partitionsDel);
//        echo '桌台';
//        dump($partitionTablesInsert);
//        dump($partitionTablesUpdate);
//        dump($partitionTablesDelIds);
//        dump($partitionTablesDel);die;
        if($updateCountPartitions !=count($oldPartitions)){
            throw new BusinessException('提交编辑的区域数据量必须等于原始数据');
        }


//        ;

        DB::beginTransaction();
        try {
            //编辑
            $this->updatePartitionsData($partitionsUpdate,$partitionTablesUpdate);
            //删除
            $this->delPartitionsData($partitionsDelIds,$partitionsDel,$partitionTablesDel);
            //新增
            $this->insertPartitionData($storeId,$partitionsInsert,$partitionTablesInsert);
        }catch (\Exception $e){
            DB::rollBack();
            throw new BusinessException($e->getMessage());
        }

        DB::commit();
        return "保存成功";
    }

    private function insertPartitionData($storeId,$partitionsInsert,$partitionTablesInsert)
    {
        PartitionModel::insert($partitionsInsert);
        $partitionIds = $this->getPartitions($storeId);//todo 删除的名字有bug
        if($partitionIds) $partitionIds = array_column($partitionIds,'id','name');

        foreach ($partitionTablesInsert as $k=>$v)
        {
            if(!isset($partitionIds[$v['partition']])){
                //echo $v['partition'];
                DB::rollBack();

                throw new BusinessException('数据异常');
            }
            $partitionTablesInsert[$k]['partition_id']=$partitionIds[$v['partition']];
            unset($partitionTablesInsert[$k]['partition']);
        }


        PartitionTable::insert($partitionTablesInsert);
    }

    private function updatePartitionsData($partitionsUpdate,$partitionTablesUpdate)
    {

            foreach ($partitionsUpdate as $k=>$v)
            {
                PartitionModel::where('id',$k)->update($v);
            }


            foreach ($partitionTablesUpdate as $k=>$v)
            {
                PartitionTable::where('id',$k)->update($v);
            }

    }

    private function delPartitionsData($partitionsDelIds,$partitionsDel,$partitionTablesDel)
    {

        $updateData = [
            'deleted_at'=>date('Y-m-d H:i:s')
        ];
        if($partitionsDelIds){
            PartitionTable::whereIn('partition_id',$partitionsDelIds)->whereNull('deleted_at')->update($updateData);
        }
        foreach ($partitionsDel as $k=>$v){
            DB::table('partitions')->where('id',$k)->update($v);
        }

        foreach ($partitionTablesDel as $k=>$v){
            PartitionTable::where('id',$k)->update($v);
        }


    }


    public function store($data)
    {
        if(empty($data['partitions'])){
            return $this->delDataByStoreId($data['store_id']);
        }
        //todo 提交校验：有进行中的订单的桌号，不允许提交，报错告诉保存失败，告诉原因 嘛
        //事务处理
        DB::beginTransaction();
        //查订单状态 todo
        $dealData = $this->dealData($data);
        //dump($dealData);die;

        /************************************新增***********************************/
        //添加区域数据，并获取ID
        PartitionModel::insert($dealData['partitionsInsert']);
        $partitionIds = $this->getPartitions($data['store_id']);
        if($partitionIds) $partitionIds = array_column($partitionIds,'id','name');
        //dump($partitionIds);
        foreach ($dealData['partitionTablesInsert'] as $k=>$v)
        {
            if(!isset($partitionIds[$v['partition']])){
                DB::rollBack();
                throw new BusinessException('数据异常');
            }
            $dealData['partitionTablesInsert'][$k]['partition_id']=$partitionIds[$v['partition']];
            unset($dealData['partitionTablesInsert'][$k]['partition']);
        }

//        dump($partitionTables);

        PartitionTable::insert($dealData['partitionTablesInsert']);
        /************************************编辑**********************************/
        /************************************删除**********************************/

        DB::commit();
        return '保存成功';
    }


    public function partitionOrder($ids)
    {
        DB::beginTransaction();
        foreach ($ids as $k=>$v)
        {
            PartitionModel::where('id',$v)->update(['order'=>$k+1]);
        }
        DB::commit();
        return '保存成功';
    }

    public function deletePartition($id)
    {
        $result = PartitionModel::find($id);
        if(!$result){
            throw new BusinessException('区域不存在');
        }
        //校验有没有使用中的台面
        $this->checkStatus($id);
        DB::beginTransaction();
        $update = ['deleted_at'=>date('Y-m-d H:i:s')];
        //删除区域
        $del = PartitionModel::where('id',$id)->update($update);
        //删除台面
        if($del){
            PartitionTable::where('partition_id',$id)->update($update);
        }
        DB::commit();
        return '删除成功';
    }

    public function changeState($id)
    {
        //停用的时候确认当前桌台没有在使用中
        $info = $this->getTableInfo($id);
        $state = (int)!$info['state'];
        //确认当前非使用中状态才可以停用
        if($state==0 && $info['status']!=1){
            throw new BusinessException('使用中桌台不可停用');
        }
        PartitionTable::where('id',$id)->update(['state'=>$state,'status'=>$state]);
        return '保存成功';
    }


    public function deleteTable($id)
    {
        $info = $this->getTableInfo($id);
        if($info['state']!=0){
            throw new BusinessException('非停用桌台不可删除');
        }
        PartitionTable::where('id',$id)->update(['deleted_at'=>date('Y-m-d H:i:s')]);
        return '删除成功';
    }

    private function getTableInfo($id)
    {
        $info =  PartitionTable::find($id)->toArray();
        if(!$info){
            throw new BusinessException('数据异常～');
        }
        if($info['deleted_at']){
            throw new BusinessException('已删除桌台不可编辑');
        }
        return $info;
    }

    private function checkStatus($partitionId)
    {
        $where=[
            'partition_id'=>$partitionId,
            'status'=>2
        ];
        $exists = PartitionTable::where($where)->exists();
        if($exists){
            throw new BusinessException('当前区域有桌台在使用中，不可删除');
        }
    }

    private function getAllPartitions($storeId)
    {
        return DB::table("partitions")
            ->where('store_id',$storeId)
            ->orderBy('order','asc')
            //->orderByRaw('order=0,order asc')
            ->get(['id','store_id','name','order','deleted_at'])->toArray();
    }


    private function getPartitions($storeId)
    {
        return PartitionModel::where('store_id',$storeId)->orderBy('order','asc')
            ->get(['id','store_id','name','order'])->toArray();
    }

    private function getPartitionTables($ids)
    {
        return PartitionTable::whereIn('partition_id',$ids)
            ->orderBy('order','asc')
            //->orderByRaw('order=0,order asc')
            ->get(['id','partition_id','number','max','state','status','deleted_at','order'])
            ->toArray();
    }


    private function dealData($data)
    {
        $storeId = $data['store_id'];

        //判断区域名称是否重复
        $partitionNames = array_column($data['partitions'],'name');
        if(count($partitionNames)>10){
            throw new BusinessException('最多10个区域');
        }
        if(count(array_unique($partitionNames)) != count($partitionNames)){
            throw new BusinessException('区域名不可重复');
        }

        $partitionsInsert = $partitionsUpdate = $partitionsDel = [];
        $partitionTablesInsert = $partitionTablesUpdate = $partitionTablesDel = [];
        foreach ($data['partitions'] as $k=>$v){
            $partitionData = [
                'store_id'=>$storeId,
                'name'=>$v['name'],
                'order'=>$k+1
            ];
            if($v['id']==0){
                array_push($partitionsInsert,$partitionData);
            }else{
                $partitionsUpdate[$v['id']] = $partitionData;
                //array_push($partitions_update,$partitionData);
            }


            //判断区域内桌号是否重复
            $tableNumbers = array_column($v['partition_tables'],'number');
            if(count($tableNumbers)>300){
                throw new BusinessException('最多添加300张桌子');
            }
            if(count(array_unique($tableNumbers)) != count($tableNumbers)){
                throw new BusinessException('区域内桌号不可重复');
            }

            foreach ($v['partition_tables'] as $o=>$t){
                if($t['id']==0){
                    array_push($partitionTablesInsert,[
                        'partition'=>$v['name'],
                        'partition_id'=>$v['id'],
                        'number'=>$t['number'],
                        //'min'=>$t['min'],
                        'order'=>$o+1,
                        'max'=>$t['max'],
                        'state'=>$t['state'],
                        'status'=>$t['state']
                    ]);
                }else{
                    $t['order']=$o+1;
                    $partitionTablesUpdate[$t['id']]=$t;
                }

            }
        }
        //dump($partitionsUpdate);
        //编辑数组为空时 删除原来store下的区域&&桌台数据数据
        if(empty($partitionsUpdate))
        {
            $this->delDataByStoreId($storeId);
        }else{
            //编辑数组存在时 对比数据  编辑或者删除

            //echo 'old';
            $oldPartitions = $this->getPartitions($storeId);
//            dump($oldPartitions);
            if(empty($oldPartitions)) throw new BusinessException('数据异常,请求编辑数据，但历史数据为空');
            foreach ($oldPartitions as $v)
            {
                if(!isset($partitionsUpdate[$v['id']])){
                    //删除数据
                    array_push($partitionsDel,$v['id']);
                    continue;
                }
                //对比数据确认是否编辑
                if($v['name']==$partitionsUpdate[$v['id']]['name'] && $v['order']==$partitionsUpdate[$v['id']]['order']){
                    unset($partitionsUpdate[$v['id']]);
                }
            }

            $partitionUpdateIds = array_merge($partitionsDel,array_keys($partitionsUpdate));//要编辑或者删除的区域ID

//            dump($partitionTablesUpdate);
            //桌台和区域分开对比
            //if($partitionTablesUpdate){
                //原始桌台数据
                $oldPartitionIds = array_column($oldPartitions,'id');
                $oldTableInfo = PartitionTable::whereIn('partition_id',$oldPartitionIds)
                    ->whereNull('deleted_at')
                    ->get(['id','number','state','status','max','partition_id','order'])->toArray();
//                echo 'old';
//                dump($oldTableInfo);
                foreach ($oldTableInfo as $v)
                {
                    if(in_array($v['partition_id'],$partitionUpdateIds) && $v['status']==2)throw new BusinessException('区域下有使用中桌台'.$v['number'].'不可编辑或删除');

                    if(!isset($partitionTablesUpdate[$v['id']]))
                    {
                        if($v['state']!=0)throw new BusinessException('桌台'.$v['number'].'为启用状态不可删除');
                        array_push($partitionTablesDel,$v['id']);
                        continue;
                    }

                    if($v['number']==$partitionTablesUpdate[$v['id']]['number']  && $v['order']==$partitionTablesUpdate[$v['id']]['order']&&
                        $v['max']==$partitionTablesUpdate[$v['id']]['max'] && $v['state']==$partitionTablesUpdate[$v['id']]['state']){
                        unset($partitionTablesUpdate[$v['id']]);
                        continue;
                    }
                    if($v['status']==2)throw new BusinessException('桌台'.$v['number'].'正在使用中不可编辑');
                    $partitionTablesUpdate[$v['id']]['status'] = $partitionTablesUpdate[$v['id']]['state'];

                //}


            }


            //编辑
            if($partitionsUpdate){
                foreach ($partitionsUpdate as $k=>$v)
                {
                    PartitionModel::where('id',$k)->update($v);
                }
            }
            if($partitionTablesUpdate){
                foreach ($partitionTablesUpdate as $k=>$v)
                {
                    PartitionTable::where('id',$k)->update($v);
                }
            }

            //删除
            $updateData = [
                'deleted_at'=>date('Y-m-d H:i:s')
            ];
            if($partitionsDel){
                PartitionModel::whereIn('id',$partitionsDel)->update($updateData);
                PartitionTable::whereIn('partition_id',$partitionsDel)->update($updateData);
            }
            if($partitionTablesDel){
                PartitionTable::whereIn('id',$partitionTablesDel)->update($updateData);
            }

        }

        return [
            'partitionsInsert'=>$partitionsInsert,
//            'partitionsUpdate'=>$partitionsUpdate,
//            'partitionsDel'=>$partitionsDel,
            'partitionTablesInsert'=>$partitionTablesInsert,
//            'partitionTablesUpdate'=>$partitionTablesUpdate,
//            'partitionTablesDel'=>$partitionTablesDel,
        ];


    }


    private function delDataByStoreId($storeId)
    {
        //通过店铺ID查区域
        $partitionInfo = $this->getPartitions($storeId);
        if(empty($partitionInfo)) return true;
        $partitionIds = array_column($partitionInfo,'id');
        //通过区域查桌台  存在使用中桌台不可删除
        $tableUsed = PartitionTable::whereIn('partition_id',$partitionIds)
            ->where('state',1)->whereNull('deleted_at')->exists();
        //get(['id','number','state','status'])->toArray();
        if($tableUsed) throw new BusinessException('删除了启用中桌台，保存失败');

        //删除区域 && 桌台
        $updateData = [
            'deleted_at'=>date('Y-m-d H:i:s')
        ];
        PartitionModel::where('store_id',$storeId)
            ->whereNull('deleted_at')->update($updateData);
        PartitionTable::whereIn('partition_id',$partitionIds)
            ->whereNull('deleted_at')->update($updateData);
        return true;

    }


    /**
     * @param $params
     * @store_id 门店ID
     * @partition_id 区域ID
     * @state 状态 0：停用  1：可用  2：已用
     */
    public function tableList($params)
    {
        $partitions = $this->getPartitions($params['store_id']);
        if(!$partitions){
            return [];
        }

        $where = [
            'p.store_id'=>$params['store_id'],
            'p.deleted_at'=>null,
        ];
        $ptWhere = [
            'pt.deleted_at'=>null,
        ];
        if(isset($params['partition_id'])){
            $where['p.id'] = $params['partition_id'];
        }
        if(isset($params['state'])){
            $ptWhere['pt.state'] = $params['state']>=1?1:0;
            $ptWhere['pt.status'] = $params['state'];
        }
        //dump($ptWhere);
        $where = array_merge($where,$ptWhere);
        //开台记录表
        $data = DB::table('partitions','p')
            ->where($where)
            ->join('partition_tables as pt',function ($join)use($ptWhere){
                $join->on('pt.partition_id','=','p.id');
                //->orderBy('pt.order','asc');
                    ///->where($ptWhere)
                    //->whereNull('pt.deleted_at');
            },null,null,'left' )

            ->join('partition_table_records as ptr',function ($join){
                $join->on('ptr.partition_table_id','=','pt.id')
                    ->where('ptr.cleared',0)
                    ->whereNull('ptr.deleted_at');
            },null,null,'left' )
//            ->join('partition_table_orders as pto',function ($join)use($ptWhere){
//                $join->on('pto.partition_table_record_id','=','ptr.id')
//                    //->where($ptWhere)
//                    ->whereNull('pto.deleted_at');
//            },null,null,'left' )

            //->leftJoin('partition_tables as pt','pt.partition_id','=','p.id')
            ->orderBy('p.order','asc')
            ->orderByRaw('pt.order=0,pt.order')
            ->get(['p.id','p.name','p.order',
                'pt.partition_id','pt.state','pt.status','pt.max', 'pt.number','pt.id as partition_table_id',
                'pt.deleted_at','pt.order as table_order',
                'ptr.id as partition_table_record_id','ptr.actual_number','ptr.created_at'])
                //'pto.amount','pto.order_no','ptr.order_no','ptr.food_order_no'])
            ->toArray();
        //dump($data);

        $res = [];
        foreach ($data as $v)
        {
            //开桌、服务时间  订单金额 订单号跳转订单详情  实际就餐人数
            $v->service_time = [];
            $v->show_state = $v->status??$v->state;
            $v->table_number = $v->name.$v->number;
            if($v->created_at){
                //时间处理
                $time = time()-strtotime($v->created_at);
                $v->service_time = $this->dealTime($time);
            }
            if(!isset($res[$v->id])){
                $res[$v->id] = [
                    'id'=>$v->id,
                    'name'=>$v->name,
                    'available'=>0,
                    'total'=>0,
                    'partition_tables'=>[],//array_values()
                ];
            }
            if(isset($res[$v->id]) && $v->partition_table_id){
                //array_push($res[$v->id]['partition_tables'],$v);
                //if($v->partition_table_id){


                if(!isset($res[$v->id]['partition_tables'][$v->partition_table_id])){
                    $res[$v->id]['partition_tables'][$v->partition_table_id] = $v;
                    //$res[$v->id]['partition_tables'][$v->partition_table_id]->orders =$v->order_no?[$v->order_no]:[];
                }else{
                    //$res[$v->id]['partition_tables'][$v->partition_table_id]->amount=$res[$v->id]['partition_tables'][$v->partition_table_id]->amount+$v->amount;
                    //array_push($res[$v->id]['partition_tables'][$v->partition_table_id]->orders,$v->order_no);
                }
                if($v->show_state==1)$res[$v->id]['available']++;
                $res[$v->id]['total']++;
                //}
            }

        }
        //dump($res);
        foreach ($res as $k=>$r)
        {
            $r['partition_tables']= array_values($r['partition_tables']);
            $res[$k] = $r;
        }
        $res = array_values($res);
        return [
            'partitions'=>$partitions,
            'tables'=>$res
        ];
    }

    private function dealTime($time)
    {

        $value = [];
        if($time >= 3600){
            $value["hours"] = (int)floor($time/3600);
            $time = ($time%3600);
        }else{
            $value["hours"] = 0;
        }

        if($time >= 60){
            $value["minutes"] = (int)ceil($time/60);
        }else{
            $value["minutes"] = 1;
        }
        return $value;
    }


    /**
     * 开台
     *
     */
    public function openTable($params)
    {
        //确认台面为可用状态
        $this->checkTableStatus($params['partition_table_id']);

        DB::beginTransaction();
        $id = PartitionTableRecord::insertGetId($params);
        //更新台面使用状态
        PartitionTable::where('id',$params['partition_table_id'])->update(['status'=>2]);
        DB::commit();
        return [
            'partition_table_record_id'=>$id,
            //'food_order_no'=>$params['food_order_no'],
            'partition_table_id '=>$params['partition_table_id'],
            ];
    }


    /**
     * 换桌
     * 'partition_table_id','original_partition_table_id'
     */
    public function changeTable($params)
    {
        if($params['partition_table_id']==$params['original_partition_table_id']) return '目标桌台与当前桌台一致';
        $this->checkTableStatus($params['partition_table_id']);

        $where = [
            'partition_table_id'=>$params['original_partition_table_id'],
            'cleared'=>0//服务中
        ];
        $exists = PartitionTableRecord::where($where)->exists();
        if(!$exists) throw new BusinessException('当前桌台不支持换桌操作');


        //数据转移 新的桌台ID替换原有的桌台ID 不需要保留原有使用记录
        DB::beginTransaction();
        PartitionTableRecord::where($where)->update(['partition_table_id'=>$params['partition_table_id']]);
        //原桌台改为可用状态
        PartitionTable::where('id',$params['original_partition_table_id'])->update(['status'=>1]);
        PartitionTable::where('id',$params['partition_table_id'])->update(['status'=>2]);
        DB::commit();
        return '换桌成功';
    }



    private function checkTableStatus($id)
    {
        $res = PartitionTable::whereNull('deleted_at')->find($id);
        if(!$res) throw new BusinessException('桌台不存在或已被删除');
        if($res->status!=1) throw new BusinessException('桌台状态不可用');
    }


    /**
     * 清桌
     */
    public function clearTable($id,$where)
    {
        //是否需要确认订单是否已支付完成  防止支付卡住的情况，因此无需验证是否支付
        DB::beginTransaction();
        PartitionTableRecord::where($where)->update(['cleared'=>1]);
        //原桌台改为可用状态
        PartitionTable::where('id',$id)->update(['status'=>1]);
        DB::commit();
        return '清桌成功';
    }

    public function generateQrcode($id)
    {
        //如果此ID下已生成二维码，不再生成，直接展示
        $url = PartitionTable::where('id',$id)->get(['qrcode_image'])->toArray();
        if(!$url){
            throw new BusinessException('桌台不存在，桌台ID：'.$id);
        }
        if($url[0]['qrcode_image']){
            return $url[0]['qrcode_image'];
        }

        $filename = md5(time());
        $extension = 'png';
        $path = storage_path('/app/public/'.$filename.'.'.$extension);

        $content = $this->encrypt(json_encode(['store_id'=>$id]));
        QrCode::size(250)->margin(10)->format($extension)->generate($content, $path);
        $url = 'http://pawhub.local.cn:8002/storage/'.$filename.'.'.$extension;

        //todo 上传到oss
        //$security = $this->getStsToken();
        //$object = env('OSS_OBJECT_PREFIX').'/qrcode/'.$filename.'.'.$extension;
        //$stsOss = StsOss::getInstance($security['id'],$security['secret'],$security['token']);
        //$url = $stsOss ->uploadImage(config('oss.bucket'), $object, $path);
        //unlink($path);//删除本地文件
//        if(!$url){
//            return Result::error('二维码生成失败');
//        }

        //$url = env('CDN_URL').'/'.$object;
        //上传阿里云之后删除本地文件  更新数据库中二维码
        $update = PartitionTable::where('id',$id)->update(['qrcode_image'=>$url]);
        //$url = $stsOss->getImage(config('oss.bucket'), $object);//生成签名URL
        if(!$update){
            throw new BusinessException('二维码生成失败,update:'.$update);
        }
        return $url;
    }

    public function changeUser($params)
    {
        $this->checkRecord($params['partition_table_record_id']);
        $update =  PartitionTableRecord::where('id',$params['partition_table_record_id'])
            ->update(['manage_no'=>$params['manage_no']]);
        if($update===false) return '更新失败';
        return '更新成功';
    }

    private function checkRecord($recordId)
    {
        $exists = PartitionTableRecord::where('id',$recordId)->exists();
        if(!$exists)throw new BusinessException('不存在ID为'.$recordId.'的开台记录');
        return $exists;
    }

    public function tableDetail($tableId)
    {
        $data = DB::table('partition_table_records as ptr')
            ->where('ptr.partition_table_id',$tableId)
            ->where('ptr.cleared',0)
            ->whereNull('pt.deleted_at')
//            ->Join('partition_tables as pt',function ($join)use($tableId){
//                $join->on('pt.id','=','ptr.partition_table_id')
//                    ;
//            },null,null,'left')
            ->leftJoin('partition_tables as pt','pt.id','=','ptr.partition_table_id')
            ->leftJoin('partitions as p','p.id','=','pt.partition_id')
            ->get(['p.id as partition_id','p.name as partition_name','p.store_id',
                'pt.id as partition_table_id','pt.max', 'pt.number',
                'ptr.id as partition_table_record_id','ptr.actual_number','ptr.created_at','ptr.manage_no',
                'ptr.cleared'//,'ptr.order_no','ptr.food_order_no'
            ])
            ->toArray();
        //dump($data);
        if(!$data)throw new BusinessException('未查询到对应桌台开台信息');
        $data = (array)$data[0];
        if($data['created_at']){
            //时间处理
            $data['created_at'] = time()-strtotime($data['created_at']);
            $data['service_time'] = $this->dealTime($data['created_at']);
        }
        $data['table_number'] = $data['partition_name'].$data['number'];
        //$data['pay_state'] = 0;


        return $data;

    }


    public function getTableRecordByManageNo($manageNo)
    {
        $where = [
            'ptr.manage_no'=>$manageNo,
            'ptr.cleared'=>0,
            'ptr.deleted_at'=>null
        ];
        $data = DB::table('partition_table_records as ptr')
            ->where($where)
            ->leftJoin('partition_tables as pt','pt.id','=','ptr.partition_table_id')
            ->leftJoin('partitions as p','p.id','=','pt.partition_id')
            ->get(['p.id as partition_id','p.name as partition_name','p.store_id',
                'pt.id as partition_table_id','pt.max', 'pt.number',
                'ptr.id as partition_table_record_id','ptr.actual_number','ptr.created_at','ptr.manage_no',
                //'ptr.order_no','ptr.food_order_no',
            ])
            ->toArray();
        //dump($data);
        if(!$data)return [];

        foreach ($data as $v){
            $v->service_time = $this->dealTime(time()-strtotime($v->created_at));
            $v->table_number = $v->partition_name.$v->number;
            $v->sum_price = 0;
        }
        //dump($data);

        return $data;
    }

    public function storeTableRecord($data)
    {
        $storeId = $data['store_id'];
        $where = [
            'p.store_id'=>$storeId,
            'p.deleted_at'=>null,
            //'ptr.manage_no'=>$manageNo,
            'ptr.cleared'=>0,
            'ptr.deleted_at'=>null
        ];

        $list = DB::table('partitions as p')
            ->where($where);
        if(isset($data['manage_no']) && !empty($data['manage_no'])){
            $list = $list->whereIn('manage_no',$data['manage_no']);
        }

        $list = $list->whereNotNull('ptr.manage_no')
        ->leftJoin('partition_tables as pt','pt.partition_id','=','p.id')
        ->leftJoin('partition_table_records as ptr','pt.id','=','ptr.partition_table_id')
        ->get(['p.store_id','p.id as partition_id','p.name as partition_name',
            'pt.id as partition_table_id', 'pt.number',
            'ptr.id as partition_table_record_id','ptr.manage_no',
            //'ptr.order_no','pt.max','ptr.actual_number','ptr.created_at',
        ])
        ->toArray();
        foreach ($list as $k=>$v)
        {
            if(empty($v->manage_no)){
                unset($list[$k]);
            }
        }
        return array_values($list);
    }

    public function rollbackAdjustment($data)
    {
        return false;
//        return PartitionAdjustmentAmount::where([
//                'order_no'=>$data['order_no'],
//                'order_type'=>$data['order_type'],
//            ])
//            ->update(['deleted_at'=>date("Y-m-d H:i:s")]);
    }


}